package com.sugon.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.consts.ErmsCodePrefix;
import com.sugon.dao.*;
import com.sugon.entity.*;
import com.sugon.entity.dto.DevRepairTicketExportParam;
import com.sugon.modules.device.consts.DevRepairTicketStage;
import com.sugon.service.*;
import com.sugon.utils.*;
import com.sugon.utils.excel.ExcelImport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 维修工单管理Service实现类
 *
 * @author sugon
 * @date 2019-07-12 11:39:29
 */
@Service("devMaintenWorkService")
public class DevMaintenWorkServiceImpl implements DevMaintenWorkService {
    @Autowired
    private DevMaintenWorkDao devMaintenWorkDao;
    @Autowired
    private DevMaintenRepairDao devMaintenRepairDao;
    @Resource
    private DevMaintenRepairService repairRecordService;
    @Autowired
    private SysProcessInfoDao sysProcessInfoDao;
    @Autowired
    private SysProcessInfoService sysProcessInfoService;
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private DevTimingTaskService devTimingTaskService;
    @Autowired
    private SysMsgService sysMsgService;
    @Autowired
    private DeviceInfoDao deviceInfoDao;
    @Resource
    private SysUserService userService;
    @Resource
    private FaultTypeDao faultTypeDao;

    /**
     * prepareExportData
     *
     * @param params
     * @return
     */
    @Override
    public List<DevRepairTicketExportParam> prepareExportData(Map<String, Object> params) {
        List<DevRepairTicketExportParam> exportDataList = devMaintenRepairDao.prepareExportData(params);
        return Optional.ofNullable(exportDataList).orElse(CollectionUtil.newArrayList());
    }

    /**
     * queryObject
     *
     * @param id 主键
     * @return
     */
    @Override
    public DevMaintenWorkEntity queryObject(String id) {
        return devMaintenWorkDao.queryObject(id);
    }

    @Override
    public List<DevMaintenWorkEntity> queryByDevId(String devId, Integer devStatus) {
        DevMaintenWorkEntity queryParam = new DevMaintenWorkEntity();
        queryParam.setDevId(devId);
        queryParam.setDevStatus(devStatus);
        return queryList(BeanUtil.beanToMap(queryParam));
    }

    /**
     * queryList
     *
     * @param map 参数
     * @return
     */
    @Override
    public List<DevMaintenWorkEntity> queryList(Map<String, Object> map) {
        return devMaintenWorkDao.queryList(map);
    }

    /**
     * queryTotal
     *
     * @param map 参数
     * @return
     */
    @Override
    public int queryTotal(Map<String, Object> map) {
        return devMaintenWorkDao.queryTotal(map);
    }

    /**
     * save
     *
     * @param devMaintenWork 实体
     * @return
     */
    @Override
    public int save(DevMaintenWorkEntity devMaintenWork) {
        //添加数据到工单表
        devMaintenWork.setId(RandomUtil.randomString(32));
        if (StrUtil.isEmpty(devMaintenWork.getRepairCode())) {
            devMaintenWork.setRepairCode(generateUniqueCode(devMaintenWork));
        }
        // 默认为未催办
        devMaintenWork.setUrgeStatus(0);
        // 默认为未超时
        devMaintenWork.setIsOvertime(0);
        devMaintenWork.setDelFlag(1);
        devMaintenWork.setCreateTime(DateUtil.date());
        // 如果未设置创建人员，那么默认为当前系统用户
        if (StrUtil.isEmpty(devMaintenWork.getCreateBy())) {
            devMaintenWork.setCreateBy(ShiroUtils.getUserRealName());
        }
        return devMaintenWorkDao.save(devMaintenWork);
    }

    @Override
    public String generateUniqueCode(Object object) {
        // 工单编号的日期部分：优先根据开始维修的那一天，如果没有则默认为当前
        Date startRepairTime = null;
        if (object != null) {
            DevMaintenWorkEntity repairTicket = (DevMaintenWorkEntity) object;
            startRepairTime = repairTicket.getStartRepairTime();
        }
        if (startRepairTime == null) {
            startRepairTime = cn.hutool.core.date.DateUtil.date();
        }

        String dateStr = cn.hutool.core.date.DateUtil.format(startRepairTime, DatePattern.PURE_DATE_PATTERN);
        String repairTicketCodePrefix = ErmsCodePrefix.MAINTENANCE_TICKET_CODE_PREFIX + dateStr + "-";
        String lastestRepairTicketCode = devMaintenWorkDao.getLastestRepairTicketCode(repairTicketCodePrefix);
        if (StrUtil.isEmpty(lastestRepairTicketCode)) {
            return repairTicketCodePrefix + "0001";
        } else {
            return com.sugon.modules.utils.StrUtil.increase(lastestRepairTicketCode, repairTicketCodePrefix, 4, 1);
        }
    }

    /**
     * update
     *
     * @param devMaintenWork 实体
     * @return
     */
    @Override
    public int update(DevMaintenWorkEntity devMaintenWork) {
        if (StrUtil.isEmpty(devMaintenWork.getUpdateBy())) {
            devMaintenWork.setUpdateBy(ShiroUtils.getUserRealName());
        }
        devMaintenWork.setUpdateTime(DateUtil.date());
        return devMaintenWorkDao.update(devMaintenWork);
    }

    /**
     * delete
     *
     * @param id
     * @return
     */
    @Override
    public int delete(String id) {
        return devMaintenWorkDao.delete(id);
    }

    /**
     * deleteBatch
     *
     * @param ids
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteBatch(String[] ids) {
        // 删除维修工单
        int deleteNum = devMaintenWorkDao.deleteBatch(ids);
        // 删除关联的维修记录
        devMaintenRepairDao.deleteByTicketIds(ids);
        return deleteNum;
    }

    /**
     * report
     *
     * @param id
     * @return
     */
    @Override
    public int report(String id) {
        /**
         * 维修人员未完成进行提报
         */
        //根据当前用户部门id 查询所属科室
        String type = sysDeptService.getDeptTypeById(ShiroUtils.getDeptId());
        if ("DT_SBWXZ".equals(type)) {//维修组人员  jsy技术员
            DevMaintenWorkEntity devMaintenWorkEntity = new DevMaintenWorkEntity();
            devMaintenWorkEntity.setId(id);
            devMaintenWorkEntity.setProcessNode(3);
            devMaintenWorkDao.update(devMaintenWorkEntity);

            DevMaintenWorkEntity entity = devMaintenWorkDao.queryObject(id);
            String user = entity.getRepairUser();//指派人id
            //更新原流程
            SysProcessInfoEntity process = new SysProcessInfoEntity();
            process.setProcessId(id);
            process.setOldApprovalStatus(0);//将0改为10  流程通过,业务未完成
            process.setApprovalType(ProcessInfoEnum.DEV_ZXGD.name());
            process.setOldApproverId(user);
            //更新语句
            sysProcessInfoService.updateOutTime(process);
            //添加定时任务倒计时
            devTimingTaskService.saveTask(id, 2);
            //添加机电设备工程师部门
            String jdsbDept = devMaintenWorkDao.getZZC();//制造处下的设备技术室id
            //机电工程师直接接单
            jdFixByJsy(id);

            return sysProcessInfoService.saveProcessInfo(id, ProcessInfoEnum.DEV_ZXGD, 1, jdsbDept, "技术员-维修人员未完成转至机电设备工程师处");
            // sysProcessInfoService.saveProcessInfoBySys(id, ProcessInfoEnum.DEV_ZXGD, 2, jdsbDept, "");
        } else {
            DevMaintenWorkEntity devMaintenWorkEntity = new DevMaintenWorkEntity();
            devMaintenWorkEntity.setId(id);
            devMaintenWorkEntity.setProcessNode(4);
            devMaintenWorkDao.update(devMaintenWorkEntity);
            //到pe人员处理,更新机电设备工程师状态,
            SysProcessInfoEntity sysProcessInfoEntity = new SysProcessInfoEntity();
            sysProcessInfoEntity.setProcessId(id);
            sysProcessInfoEntity.setOldApprovalStatus(2);//将状态为2的数据更新为未完成
            sysProcessInfoEntity.setApprovalType(ProcessInfoEnum.DEV_ZXGD.name());
            sysProcessInfoDao.updateOutTime120(sysProcessInfoEntity);
            //pe人员消息提醒
            SysMsgEntity msgEntity = new SysMsgEntity();
            msgEntity.setDataType(ProcessInfoEnum.DEV_ZXGD.name());
            msgEntity.setDataUrl("/device/devmaintenwork.html");
            msgEntity.setTitle("设备维修工单");
            msgEntity.setType(SysMsgType.REPAIR_REMIND);
            msgEntity.setStartDate(new Date());
            msgEntity.setUserId(ShiroUtils.getUserId());
            sysMsgService.allMsgData(msgEntity);
            //更新task表的状态
            devTimingTaskService.deleteByProcessId(2, id);
            String pe = sysDeptService.getPEdept("DT_ZZC");//获取pe人员
            //添加新纪录
            return sysProcessInfoService.
                    saveProcessInfoBySys(id, ProcessInfoEnum.DEV_ZXGD, 10, pe, "机电工程师-机电工程师未完成转至pe授权人员处");
        }
    }

    /**
     * getRepairUser
     *
     * @return
     */
    @Override
    public List getRepairUser() {
        // 获取当前部门下技术人员
        return devMaintenWorkDao.getRepairUser(ShiroUtils.getDeptId());
    }

    /**
     * jdFixByJsy
     *
     * @param id
     * @return
     */
    //维修人员转交到机电设备工程师
    @Override
    public int jdFixByJsy(String id) {
        //删除维修人员指派人和辅修人员
        updateFixer(id);
        //维修人员状态改为未完成
        SysProcessInfoEntity oldProcessInfoEntity = new SysProcessInfoEntity();
        oldProcessInfoEntity.setProcessId(id);//旧流程id
        oldProcessInfoEntity.setOldApprovalStatus(2);//将2变为1
        oldProcessInfoEntity.setApprovalType(ProcessInfoEnum.DEV_ZXGD.name());
//        oldProcessInfoEntity.setNewApproverId();   //更新维修组长审批记录
        sysProcessInfoDao.updateOutTime(oldProcessInfoEntity);
        //机电工程师消息提醒
        SysMsgEntity msgEntity = new SysMsgEntity();
        msgEntity.setDataType(ProcessInfoEnum.DEV_ZXGD.name());
        msgEntity.setDataUrl("/device/devmaintenwork.html");
        msgEntity.setTitle("设备维修工单");
        msgEntity.setType(SysMsgType.REPAIR_REMIND);
        msgEntity.setStartDate(new Date());
        msgEntity.setUserId(ShiroUtils.getUserId());
        sysMsgService.allMsgData(msgEntity);
        //添加机电工程师开始执行
        return sysProcessInfoService.saveProcessInfo(
                id, ProcessInfoEnum.DEV_ZXGD, 2, "", "维修人员-维修人员上报机电工程师执行维修");
    }

    /**
     * Auxiliary
     *
     * @param id
     * @return
     */
    @Override
    public int Auxiliary(String id) {
        String userId = ShiroUtils.getUserId();
        return devMaintenWorkDao.getAuxiliary(id, userId);
    }

    /**
     * update8D
     *
     * @param id
     * @return
     */
    @Override
    public int update8D(String id) {
        return devMaintenWorkDao.updateED(id);
    }

    /**
     * updateStatus
     *
     * @param status
     * @param id
     * @return
     */
    @Override
    public int updateStatus(Integer status, String id) {
        return devMaintenWorkDao.updateStatus(status, id);
    }

    /**
     * updateFixer
     *
     * @param id
     * @return
     */
    @Override
    public int updateFixer(String id) {
        //删除辅修人员关系
        devMaintenWorkDao.delEquipment(id);
        //删除维修人员
        return devMaintenWorkDao.delRepairUser(id);
    }

    /**
     * loadDevByWxgdCode
     *
     * @param wxgd
     * @return
     */
    @Override
    public DeviceInfoEntity loadDevByWxgdCode(String wxgd) {
        //获取维修工单中设备编码
        DevMaintenWorkEntity dmwe = devMaintenWorkDao.queryObjectByCode(wxgd);
        String devCode = dmwe.getDevCode();
        if (StringUtils.isNotEmpty(devCode)) {
            DeviceInfoEntity die = deviceInfoDao.getInfoByDevCode(devCode);
            return die;
        } else {
            return null;
        }
    }

    /**
     * getDevPlanImplementation
     *
     * @param map 参数
     * @return
     */
    @Override
    public List<DevMaintenWorkEntity> getDevPlanImplementation(Map<String, Object> map) {
        return devMaintenWorkDao.getDevPlanImplementation(map);
    }

    /**
     * 保存或更新导入的设备清单信息
     *
     * @param file
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int batchImport(MultipartFile file) {
        int num = 0;
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        List<String[]> list = ExcelImport.getExcelData(file);
        if (CollectionUtil.isNotEmpty(list)) {
            // 获取用户姓名：用户ID组成的map列表
            List<SysUserEntity> userList = userService.queryList(MapUtil.newHashMap());
            // 过滤掉名字重复的
            userList = userList.stream().collect(
                    Collectors.collectingAndThen(
                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SysUserEntity::getNickName))), ArrayList::new)
            );
            Map<String, String> userMap = userList.stream().collect(Collectors.toMap(SysUserEntity::getNickName, SysUserEntity::getUserId));
            for (int i = 1; i < list.size(); i++) {
                String[] array = list.get(i);
                array = ArrayUtil.resize(array, 13);
                DevMaintenWorkEntity repairTicket = devMaintenWorkDao.queryObjectByCode(array[2]);
                if (repairTicket == null) {
                    repairTicket = new DevMaintenWorkEntity();
                    repairTicket.setRepairCode(array[2]);
                }
                // 设置车间和设备ID
                DeviceInfoEntity device = deviceInfoDao.getInfoByDevCode(array[1]);
                if (device != null) {
                    repairTicket.setWorkshopId(device.getDevFarm());
                    repairTicket.setDevId(device.getId());
                }
                // 设置上报人
                if (StrUtil.isNotEmpty(array[5])) {
                    repairTicket.setUploadId(userMap.get(array[5]));
                }
                // 设置上报时间
                if (StrUtil.isNotEmpty(array[3])) {
                    repairTicket.setUploadDate(cn.hutool.core.date.DateUtil.parseDateTime(array[3]));
                }
                repairTicket.setFaultCon(array[4]);
                // 设置设备状态
                repairTicket.setDevStatus(DevRepairTicketStage.CLOSE);

                // 设置维修人员
                if (StrUtil.isNotEmpty(array[6])) {
                    repairTicket.setUploadId(userMap.get(array[6]));
                }

                // 设置开始维修时间
                if (StrUtil.isNotEmpty(array[7])) {
                    repairTicket.setStartRepairTime(cn.hutool.core.date.DateUtil.parseDateTime(array[7]));
                }

                // 设置结束维修时间
                if (StrUtil.isNotEmpty(array[8])) {
                    repairTicket.setEndRepairTime(cn.hutool.core.date.DateUtil.parseDateTime(array[8]));
                }

                if (StrUtil.isNotEmpty(repairTicket.getId())) {
                    // 更新
                    num += update(repairTicket);
                    DevMaintenRepairEntity repairRecord = devMaintenRepairDao.queryByTicketId(repairTicket.getId());
                    if (repairRecord == null) {
                        repairRecord = new DevMaintenRepairEntity();
                    }
                    repairRecord.setMaintenRecordId(repairTicket.getId());
                    // 设置故障类别
                    if (StrUtil.isNotEmpty(array[11])) {
                        FaultTypeEntity faultType = faultTypeDao.queryByFaultCode(array[11]);
                        if (faultType != null) {
                            //repairRecord.setType(faultType.getId());
                        }
                    }
                    repairRecord.setRecordDescr(array[9]);
                    repairRecord.setReason(array[10]);
                    repairRecord.setSolution(array[12]);
                    // 设置维修人员
                    if (StrUtil.isNotEmpty(array[6])) {
                        repairRecord.setRepairUser(userMap.get(array[6]));
                    }
                    // 设置上报时间
                    if (StrUtil.isNotEmpty(array[3])) {
                        repairRecord.setUploadDate(cn.hutool.core.date.DateUtil.parseDateTime(array[3]));
                    }
                    // 设置开始维修时间
                    if (StrUtil.isNotEmpty(array[7])) {
                        repairRecord.setRepairStartDate(cn.hutool.core.date.DateUtil.parseDateTime(array[7]));
                    }
                    // 设置结束维修时间
                    if (StrUtil.isNotEmpty(array[8])) {
                        repairRecord.setRepairEndDate(cn.hutool.core.date.DateUtil.parseDateTime(array[8]));
                    }
                    repairRecord.setDevId(repairTicket.getDevId());
                    // 保存或更新数
                    int saveOrUpdateNum = StrUtil.isNotEmpty(repairRecord.getId()) ? repairRecordService.update(repairRecord) : repairRecordService.save(repairRecord);
                } else {
                    // 保存
                    num += save(repairTicket);
                    DevMaintenRepairEntity repairRecord = new DevMaintenRepairEntity();
                    repairRecord.setMaintenRecordId(repairTicket.getId());
                    // 设置故障类别
                    if (StrUtil.isNotEmpty(array[11])) {
                        FaultTypeEntity faultType = faultTypeDao.queryByFaultCode(array[11]);
                        if (faultType != null) {
                            //repairRecord.setType(faultType.getId());
                        }
                    }
                    repairRecord.setRecordDescr(array[9]);
                    repairRecord.setReason(array[10]);
                    repairRecord.setSolution(array[12]);
                    // 设置维修人员
                    if (StrUtil.isNotEmpty(array[6])) {
                        repairRecord.setRepairUser(userMap.get(array[6]));
                    }
                    // 设置上报时间
                    if (StrUtil.isNotEmpty(array[3])) {
                        repairRecord.setUploadDate(cn.hutool.core.date.DateUtil.parseDateTime(array[3]));
                    }
                    // 设置开始维修时间
                    if (StrUtil.isNotEmpty(array[7])) {
                        repairRecord.setRepairStartDate(cn.hutool.core.date.DateUtil.parseDateTime(array[7]));
                    }
                    // 设置结束维修时间
                    if (StrUtil.isNotEmpty(array[8])) {
                        repairRecord.setRepairEndDate(cn.hutool.core.date.DateUtil.parseDateTime(array[8]));
                    }
                    repairRecord.setDevId(repairTicket.getDevId());
                    repairRecordService.save(repairRecord);
                }
            }
        }
        return num;
    }

}
